﻿namespace TfsExtensions.Build.Activities
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Reflection;
    using System.Text.RegularExpressions;

    internal class UpdateAssemblyInfoHelper
    {
        private Regex attributeBooleanValuePattern;
        private Dictionary<string, int> attributesDictionary;
        private Regex attributeNamePattern;
        private Regex attributeStringValuePattern;
        private Regex multiLineCSharpCommentEndPattern;
        private Regex multiLineCSharpCommentStartPattern;
        private List<string> rawFileLines;
        private Regex singleLineCSharpCommentPattern;
        private Regex singleLineVbCommentPattern;

        private string fileName;

        public UpdateAssemblyInfoHelper(string filename)
        {
            this.fileName = filename;

            string str;
            this.rawFileLines = new List<string>();
            this.attributesDictionary = new Dictionary<string, int>();
            this.attributeNamePattern = new Regex(@"[aA]ssembly:?\s*(?<attributeName>\w+)\s*\(", RegexOptions.Compiled);
            this.attributeStringValuePattern = new Regex("\"(?<attributeValue>.*?)\"", RegexOptions.Compiled);
            this.attributeBooleanValuePattern = new Regex(@"\((?<attributeValue>([tT]rue|[fF]alse))\)", RegexOptions.Compiled);
            this.singleLineCSharpCommentPattern = new Regex(@"\s*//", RegexOptions.Compiled);
            this.singleLineVbCommentPattern = new Regex(@"\s*'", RegexOptions.Compiled);
            this.multiLineCSharpCommentStartPattern = new Regex(@"\s*/\*^\*", RegexOptions.Compiled);
            this.multiLineCSharpCommentEndPattern = new Regex(@".*?\*/", RegexOptions.Compiled);
            using (StreamReader reader = File.OpenText(filename))
            {
                int num = 0;
                bool flag = false;
                while ((str = reader.ReadLine()) != null)
                {
                    this.rawFileLines.Add(str);
                    if (this.singleLineCSharpCommentPattern.IsMatch(str) || this.singleLineVbCommentPattern.IsMatch(str))
                    {
                        num++;
                    }
                    else if (this.multiLineCSharpCommentStartPattern.IsMatch(str))
                    {
                        num++;
                        flag = true;
                    }
                    else
                    {
                        if (this.multiLineCSharpCommentEndPattern.IsMatch(str) && flag)
                        {
                            num++;
                            flag = false;
                            continue;
                        }
                        if (flag)
                        {
                            num++;
                            continue;
                        }
                        MatchCollection matchs = this.attributeNamePattern.Matches(str);
                        if (matchs.Count > 0)
                        {
                            for (int i = 0; i < matchs.Count; i++)
                            {
                                this.attributesDictionary.Add(matchs[i].Groups["attributeName"].Value, num);
                            }
                        }
                        num++;
                    }
                }
            }
        }

        public void Write(StreamWriter streamWriter)
        {
            foreach (string str in this.rawFileLines)
            {
                streamWriter.WriteLine(str);
            }
        }

        public string this[string attribute]
        {
            get
            {
                if (this.attributesDictionary.ContainsKey(attribute))
                {
                    MatchCollection matchs = this.attributeStringValuePattern.Matches(this.rawFileLines[this.attributesDictionary[attribute]]);
                    if (matchs.Count > 0)
                    {
                        return matchs[0].Groups["attributeValue"].Value;
                    }
                    matchs = this.attributeBooleanValuePattern.Matches(this.rawFileLines[this.attributesDictionary[attribute]]);
                    if (matchs.Count > 0)
                    {
                        return matchs[0].Groups["attributeValue"].Value;
                    }
                }
                return null;
            }
            set
            {
                if (!this.attributesDictionary.ContainsKey(attribute))
                {
                    throw new ArgumentOutOfRangeException("attribute", string.Format("{0} is not an attribute in the specified AssemblyInfo file", attribute));
                }

                if (this.attributeStringValuePattern.Matches(this.rawFileLines[this.attributesDictionary[attribute]]).Count > 0)
                {
                    this.rawFileLines[this.attributesDictionary[attribute]] = this.attributeStringValuePattern.Replace(this.rawFileLines[this.attributesDictionary[attribute]], "\"" + value + "\"");
                }
                else if (this.attributeBooleanValuePattern.Matches(this.rawFileLines[this.attributesDictionary[attribute]]).Count > 0)
                {
                    this.rawFileLines[this.attributesDictionary[attribute]] = this.attributeBooleanValuePattern.Replace(this.rawFileLines[this.attributesDictionary[attribute]], "(" + value + ")");
                }
            }
        }
    }
}

